package com.study.service.impl;

import com.study.dao.PermissionDao;
import com.study.dao.RolePermissionDao;
import com.study.entity.Permission;
import com.study.entity.PermissionVo;
import com.study.service.PermissionService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class PermissionServiceImpl implements PermissionService {
    @Autowired
    private PermissionDao permissionDao;

    @Autowired
    private RolePermissionDao rolePermissionDao;

    @Override
    public int addPermission(Permission permission) {
        return permissionDao.insertPermission(permission);
    }

    /**
     * 删除资源表资源时，先删除关联表中数据
     */
    @Override
    public int deletePermission(Integer resId) {
        rolePermissionDao.deleteByPermissionId(resId);

        return permissionDao.deletePermission(resId);
    }

    @Override
    public Permission getPermissionByResId(Integer resId) {
        return permissionDao.selectPermissionByResId(resId);
    }

    @Override
    public int modifyPermission(Permission permission) {
        return permissionDao.updatePermission(permission);
    }

    @Override
    public List<Permission> selectPermission() {
        return permissionDao.selectAllPermission();
    }

    @Override
    public List<Permission> selectPermission_enable() {
        return permissionDao.selectPermission_enable();
    }

    @Override
    public List<Permission> getParentResourceInfo(Integer level) {
        return permissionDao.getParentPermissionInfo(level);
    }


    /**
     * 对象转换 将数据库实体类对象转换成前端实体
     *
     * @param permission
     * @return
     */
    private PermissionVo resourcesTOResourcesVo(Permission permission) {
        PermissionVo permissionVo = new PermissionVo();
        BeanUtils.copyProperties(permission, permissionVo);
        return permissionVo;
    }

    @Override
    public List<PermissionVo> selectAllPermission() {
        // 获取所有的菜单目录
        List<Permission> resources = permissionDao.selectAllPermission();

        // 获取一级菜单，0 代表一级菜单
        List<PermissionVo> rootResources = resources.stream()
                .filter(e -> e.getParentId().equals(0))
                .map(this::resourcesTOResourcesVo).sorted(Comparator.comparing(PermissionVo::getPermissionId).reversed())
                .collect(Collectors.toList());

        // 查找子菜单
        findSubResources(resources, rootResources);

        return rootResources;
    }

    /**
     * 根据一级递归调用子级
     * 千万不要循环去查询数据库，这种是极度危险的行为
     *
     * @param permissionList
     * @param rootResources
     */
    private void findSubResources(List<Permission> permissionList, List<PermissionVo> rootResources) {
        // 遍历一级菜单
        for (PermissionVo permissionVo : rootResources) {
            List<PermissionVo> subPermissionVoList = new ArrayList<>();

            // 查找子级
            for (Permission permission : permissionList) {
                // 判断当前菜单是否是子父级关系
                if (permissionVo.getPermissionId().equals(permission.getParentId())) {
                    subPermissionVoList.add(resourcesTOResourcesVo(permission));
                }

                // 递归调用，不管有几级菜单，都能够适用
                findSubResources(permissionList, subPermissionVoList);

                // resId排序，reversed 表示数字越大靠前
                subPermissionVoList.sort(Comparator.comparing(PermissionVo::getPermissionId).reversed());
            }

            // 最后把查到的子级保存到父级菜单中
            permissionVo.setSubPermission(subPermissionVoList);
        }
    }

    public List<PermissionVo> getCatalogIdByUserId(Integer userId) {
        int[] resIds = rolePermissionDao.getCatalogIdByUserId(userId);
        List<PermissionVo> permissionVos = selectAllPermission();
        List<PermissionVo> permissionVos_user = new ArrayList<>();
        for (int resId : resIds) {
            for (PermissionVo permissionVo : permissionVos) {
                if (resId == permissionVo.getPermissionId()) {
                    permissionVos_user.add(permissionVo);
                }
            }
        }
        return permissionVos_user;
    }
}
